#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <time.h>

#define SIZE 125

double getTime() { 
	struct timeval time;
	gettimeofday(&time, 0); // int gettimeofday(struct timeval *, void *);
	return time.tv_sec + time.tv_usec / 1e6; // tv_sec = segundos
											 // tv_usec = microsegundos (por isso a divisao por 1 milhao)
}

void startListen() {
	int sock, connected, bytes_recv, i, true = 1;
	int recv_vector[SIZE * 8];
	struct sockaddr_in server_addr, client_addr;
	int sin_size;
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("Erro no Socket");
		exit(1);
	}

	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(int)) == -1) {
		perror("Erro Setsockopt");
		exit(1);
	}

	// Configura o endereco de destino
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(6000);
	server_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(server_addr.sin_zero), 8);

	if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
		perror("Nao foi possivel realizar o bind");
		exit(1);
	}
	
	if (listen(sock, 10) == -1) {
		perror("Erro de Listen");
		exit(1);
	}
	
	// Variavel para armazenar o tamanho de endereco do cliente conectado
	sin_size = sizeof(struct sockaddr_in);
	
	connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
	
	// Funcao recv (int socket, void *buffer, size_t size, int flags)        
	bytes_recv = recv(connected, recv_vector, sizeof(recv_vector), 0);

	for(i = 0; i < SIZE * 8; i++) {
		printf("%d ", recv_vector[i]);
	}
	close(sock);
}

int main(int argc, char *argv[]) {

	int *vector;
    int sock, i;
    double time_ord, time_send;
    char send_data[1024];
    struct hostent *host;
    struct sockaddr_in server_addr;
    
    if(argc != 2) {
        printf("Usage: %s <hostname>\n", argv[0]);
        return 1;
    }
	host = gethostbyname(argv[1]);
	
    vector = (int *)malloc(sizeof(int)*SIZE);

	srand(time(NULL));

	for(i = 0; i < SIZE; i++) {
		vector[i] = rand() % 10000;
	}
	
	time_ord = getTime();
	
	for(i = 0; i < SIZE; i++) {
		printf("%d ", vector[i]);
	}
	
	printf("\n\n");

	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("Erro de Socket");
		exit(1);
	}

	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(7000);
	server_addr.sin_addr = *((struct in_addr *)host->h_addr);
	bzero(&(server_addr.sin_zero),8);

	if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
		perror("Erro de conexao");
		exit(1);
	}
	
	time_send = getTime();
	
	send(sock, vector, SIZE * sizeof(int), 0);
	
	time_send = getTime() - time_send;
	
	close(sock);
	
	startListen();
	
	time_ord = getTime() - time_ord;
	
	printf("\nTempo de ordenacao total %f", time_ord);
	printf("\nTempo de envio %f", time_send);
	return 0;
}

